package com.example.function.integration.utils;

import cn.hutool.crypto.symmetric.AES;
import cn.hutool.crypto.symmetric.DES;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import com.example.function.integration.config.CommonResourceConfig;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

/**
 * @description:
 * @className:CryptoUtils
 * @author:ext.fengcheng
 * @date:2023/9/15 14:38
 */
public class CryptoUtils extends CommonResourceConfig {

    private static final Logger logger = LoggerFactory.getLogger(CryptoUtils.class);

    private CryptoUtils() {
    }

    private volatile static SymmetricCrypto defaultSymmetricCrypto = null;

    /**
     * 获取默认的加密对象
     *
     * @return
     */
    public static SymmetricCrypto getDefaultSymmetricCrypto() {
        if (defaultSymmetricCrypto == null) {
            synchronized (CryptoUtils.class) {
                if (defaultSymmetricCrypto == null) {
                    String crypto;
                    String secretKey;
                    try {
                        // 获取配置的加密方式
                        crypto = CommonResourceConfig.morseCryptoType;
                        // 获取配置的加密密钥
                        secretKey = CommonResourceConfig.morseCryptoSecretKey;
                    } catch (Exception e) {
                        logger.error("获取加密配置失败, 请检查【application.properties】资源文件中是否配置加密方式(morse.crypto.type)和密钥(morse.crypto.secretKey)");
                        throw e;
                    }
                    if (StringUtils.isAnyBlank(crypto, secretKey)) {
                        logger.error("获取加密配置为空, 请检查【application.properties】资源文件中是否配置加密方式(morse.crypto.type)和密钥(morse.crypto.secretKey)");
                        throw new RuntimeException("获取加密配置为空, 请检查【application.properties】资源文件中是否配置加密方式和密钥");
                    }
                    // 加密
                    SymmetricAlgorithm sa = SymmetricAlgorithm.valueOf(crypto);
                    logger.info("系统使用{}加密方式", sa.name());

                    defaultSymmetricCrypto = generateSymmetricCrypto(sa, secretKey);
                }
            }
        }
        return defaultSymmetricCrypto;
    }

    /**
     * 获取对称加密的对象
     *
     * @return
     */
    public static SymmetricCrypto generateSymmetricCrypto(SymmetricAlgorithm sa, String secretKey) {
        Assert.notNull(sa, "加密算法参数不能为空");
        Assert.notNull(secretKey, "密钥不能为空");
        SymmetricCrypto sc;
        switch (sa) {
            case AES:
                sc = new AES(secretKey.getBytes());
                break;
            case DES:
                sc = new DES(secretKey.getBytes());
                break;
            default:
                throw new IllegalArgumentException("暂不支持该种加密方式");
        }
        return sc;
    }

    /**
     * 加密函数 使用系统配置的默认加密算法和密钥进行加密
     *
     * @param encryptText
     * @return
     */
    public static String encryptMode(String encryptText) {
        if (StringUtils.isBlank(encryptText)) {
            return null;
        }
        SymmetricCrypto sc = getDefaultSymmetricCrypto();
        return sc.encryptBase64(encryptText);
    }

    /**
     * 解密函数 使用系统配置的默认加密算法和密钥进行解密
     *
     * @param decryptText
     * @return
     */
    public static String decryptMode(String decryptText) {
        if (StringUtils.isBlank(decryptText)) {
            return null;
        }
        SymmetricCrypto sc = getDefaultSymmetricCrypto();
        return sc.decryptStr(decryptText);
    }

    /**
     * 加密文件
     *
     * @param sourceFile     源文件
     * @param diminationFile 目的文件
     */
    public static void encryptFile(String sourceFile, String diminationFile) {
        SymmetricCrypto sc = getDefaultSymmetricCrypto();
        sc.encrypt(sourceFile, diminationFile);
    }

    /**
     * 解密文件
     *
     * @param sourceFile
     * @param diminationFile
     * @throws Exception
     */
    public static void decryptFile(String sourceFile, String diminationFile) {
        // SymmetricCrypto sc = getDefaultSymmetricCrypto();
        // sc.decryptStr(sourceFile, diminationFile);
    }

}
